<?php
namespace Classes;
use CURLFile;
class Lanzou {
	const API        = 'https://up.woozooo.com/doupload.php';
	const API_UPLOAD = 'https://pc.woozooo.com/fileup.php';
	const API_LOGIN  = 'https://up.woozooo.com/mlogin.php';
	const HOST       = 'https://pan.lanzouv.com/';
	const allowedExts = [
		'7z', 'accdb', 'apk', 'appimage', 'azw', 'azw3', 'bat', 'bdi', 'bds', 'cad', 'ce', 'cetrainer', 'cfg', 'conf',
		'cpk', 'crx', 'ct', 'db', 'deb', 'dll', 'dmg', 'doc', 'docx', 'dwg', 'e', 'enc', 'epub', 'exe', 'flac', 'gho',
		'hwt', 'imazingapp', 'img', 'ipa', 'ipa', 'iso', 'it', 'jar', 'ke', 'lolgezi', 'lua', 'mobi', 'mobileconfig',
		'mp3', 'osk', 'osz', 'pdf', 'pkg', 'ppt', 'pptx', 'rar', 'rp', 'rplib', 'rpm', 'ssf', 'tar', 'ttc', 'ttf',
		'txf', 'txt', 'w3x', 'xapk', 'xls', 'xlsx', 'xmind', 'xpa', 'z', 'zip'
	];
	const prefix = 'lanzou:';
	/**
	 * @var \Classes\Lanzou
	 */
	private static $INSTANCE;
	/**
	 * @var array
	 */
	private $conf;
	/**
	 * @var \Classes\Redis|null
	 */
	private $redis;
	private $conf_ylogin=0;
	/**
	 * Lanzou 初始化.
	 *
	 * @param  array  $conf
	 *
	 * @throws \Exception
	 */
	private function __construct ($conf = []) {
		if (strval(@$conf['admin_pass']) === '') $conf['admin_pass'] = 'lianyi';
		if (strval(@$conf['default_pwd']) === '') $conf['default_pwd'] = '00';
		if (!is_numeric($conf['upload_timeout']) || $conf['upload_timeout'] < 10) $conf['upload_timeout'] = 120;
		if (!isset($conf['redis']) || boolval($conf['redis']) !== false)
			$this->redis = Redis::prefix(self::prefix);
		$this->conf = $conf;
		$this->cache_clear();
	}
	/**
	 * @return $this
	 */
	private static function instance () {
		if (!(self::$INSTANCE instanceof self))
			exit(msg(-2, '尚未初始化配置'));
		return self::$INSTANCE;
	}
	/**
	 * 初始化配置
	 *
	 * @param $conf
	 *
	 * @return $this
	 * @throws \Exception
	 */
	public static function config ($conf) {
		self::$INSTANCE = $ins = new self($conf);
		return $ins;
	}
	/**
	 * 文件列表
	 *
	 * @param  string  $id    文件夹id
	 * @param  string  $pwd   文件夹密码
	 * @param  int     $page  页码
	 *
	 * @return array
	 * @throws \RedisException
	 */
	public static function parseList ($id, $pwd = '', $page = 1) {
		if ($id === '') $id = '-1';
		$page = intval($page);
		if ($page < 1) $page = 1;
		if (preg_match('/^[bi]/', $id))
			return self::shareList($id, $pwd, $page);
		$ins = self::instance();
		if (true !== $ret = $ins->getCookie())
			return $ret;
		$admin = $ins->isAdmin();
		$extra = ['admin' => true === $admin];
		if ($page === 1) {
			// 获取子文件夹及父文件夹
			$folder = $ins->cCurl(47, ['folder_id' => $id])->obj();
			if ($folder->zt !== 1 && $folder->zt !== 2)
				return msg(1, is_string($folder->info) ? $folder->info : '解析文件夹失败');
			$path = arr_column($folder->info, 'name', 'folderid');
			if ($id !== '-1' && empty($path))
				return msg(2, '文件夹不存在');
			$extra['path'] = $path;
			$folders = arr_multisort($folder->text, 'name');
		}
		if ($id !== '-1' && false === $folderInfo = $ins->folderInfo($id))
			return msg(3, '获取文件夹数据失败');
		if ($page === 1)
			$extra['desc'] = $id === '-1' || $folderInfo->des === '' ? '<a href="https://gitee.com/lianyi007/lianyi-cloud" style="color: red" target="_blank">涟漪云</a>' : html_entity_decode($folderInfo->des);
		$real_pwd = isset($folderInfo->onof) && $folderInfo->onof === '1' && isset($folderInfo->pwd) && $folderInfo->pwd !== $ins->conf['default_pwd'] ? $folderInfo->pwd : '';
		if ($real_pwd !== null && $real_pwd !== '') {
			if (true === $admin) {
				$extra['pwd'] = $real_pwd;
			} else {
				$key  = self::prefix . $id;
				$pwd2 = session($key);
				if ($pwd === '' && $pwd2 === null)
					return msg(-4, '请输入密码', $extra);
				if ($real_pwd !== $pwd && $real_pwd !== $pwd2)
					return msg(-5, '密码错误', $extra);
				session($key, $real_pwd);
			}
		}
		// 获取子文件
		$file = $ins->cCurl(5, ['folder_id' => $id, 'pg' => $page])->obj();
		if ($file->zt === 0)
			return msg(3, '解析文件夹失败', $extra);
		$files = arr_multisort($file->text, 'name_all');
		$data           = isset($folders) ? array_merge($folders, $files) : $files;
		$extra['count'] = pow(10, 6) * 18;
		if (empty($data))
			return msg(0, $page > 1 ? '没有更多文件' : '空文件夹', $extra);
        $conf_ylogin = $ins->conf['cookie']['ylogin'];
        foreach($data as $k=>$v){
			if (isset($v->id)) {
				preg_match('/^((.+?)\.([^.]+))(\.it)?$/i', $v->name_all, $m);
				$data[$k]= [
					'id'    => $v->id,
					'name'  => $m[1],
					'size'  => $v->size,
					'ext'   => $m[3],
					'downs' => $v->downs,
					'time'  => $v->time,
                    'ylogin'=> $conf_ylogin
				];
			} else {
    			 $data[$k]=[
				'id'    => $v->fol_id,
				'name'  => $v->name,
				'isdir' => true
			];
			} 
        }
		return msg(0, $data, $extra);
	}
	/**
	 * 文件列表（分享id）
	 *
	 * @param  string  $shareId  文件夹分享id
	 * @param  string  $pwd      文件夹密码
	 * @param  int     $page     页码
	 *
	 * @return array
	 * @throws \RedisException
	 */
	public static function shareList ($shareId, $pwd = '', $page = 1) {
		$page = intval($page);
		if ($page < 1) $page = 1;
		if (!preg_match('/^([bi])/', $shareId, $m))
			return msg(1, '分享id不合法');
		if ($m[1] === 'i') {
			return msg(2, '此分享id对应直链：' . request_dir() . $shareId . ($pwd === '' ? '' : '?pwd=' . $pwd));
		}
		$ins = self::instance();
		$folders = [];
		$key     = "d:{$shareId}";
		if ($page > 1 && (null !== $ajax = $ins->cache_get($key))) {
			if (array_key_exists('pwd', $ajax['data'])) {
				if ($pwd === '') return msg(3, '请输入访问密码');
				$ajax['data']['pwd'] = $pwd;
			}
		} else {
			$html = $ins->curl('android')->get(self::HOST . $shareId)->html();
			if (false !== $ajax = self::html_ajax($html)) {
				// t, k 参数有效期10分钟
				$ins->cache_set($key, $ajax, 580);
				if (array_key_exists('pwd', $ajax['data'])) {
					if ($pwd === '') return msg(3, '请输入访问密码');
					$ajax['data']['pwd'] = $pwd;
				}
				$p = preg_match_all('/class="mbx\s+mbxfolder".*?<a.*?href="([\/.]+)?(\w+?)".*?class="filename">(.+?)<div/', $html, $m2);
				$i = 0;
				while ($i < $p) {
					$folders[] = [
						'id'    => $m2[2][$i],
						'name'  => $m2[3][$i],
						'isdir' => true
					];
					$i++;
				}
			} else if (preg_match('/(<div\s+class="off\d?">){3}<\/div><\/div>(.+?)<\/div>/i', $html, $m))
				return msg(4, $m[2]);
			else
				return msg(5, '解析文件夹数据失败');
		}
		$ajax['data']['pg'] = $page;
		$url                = self::url_fix(self::HOST, $ajax['url']);
		$file               = $ins->curl()->post($url, $ajax['data'])->obj();
		if ($file->zt !== 1) {
			if ($page <= 1 && empty($folders))
				return msg(6, isset($file->info) ? $file->info : '获取文件数据失败');
			$files = [];
		} else
			$files = $file->text; // arr_multisort($file->text, 'name_all')
		if (empty($files) && empty($folders))
			return msg(8, $page > 1 ? '没有更多文件' : '空文件夹');
		$files = array_map(function ($v) {
			preg_match('/^((.+?)\.([^.]+))(\.it)?$/i', $v->name_all, $m);
			return [
				'id'   => $v->id,
				'name' => $m[1],
				'size' => $v->size,
				'ext'  => $m[3],
				'time' => $v->time
			];
		}, $files);
		$data  = $page <= 1 ? array_merge($folders, $files) : $files;
		$count = count($files);
		return msg(0, $data, [
			'count' => $count >= 50 ? pow(10, 6) * 50 : ($page - 1) * 50 + $count
		]);
	}
	/**
	 * 解析直链（文件id）
	 *
	 * @param  string  $id  文件id
	 *
	 * @return array
	 * @throws \RedisException
	 */
	public static function parseUrl ($id) {
		$ins = self::instance();
        if(strlen($id)>10 && strpos($id,'y')>0){
            $arr = explode('y',$id);$id=$arr[0];$ins->conf_ylogin=$arr[1];
        }
		$key = "f:{$id}";
		if (null !== $url = $ins->cache_get($key)) {
			header('Location: ' . $url);
			exit();
		}
		if (true !== $ret = $ins->getCookie())
			return $ret;
		if (false === $fileInfo = $ins->fileInfo($id))
			return msg(1, '解析文件信息失败');
		return self::parseUrlByShareId($fileInfo->f_id, $fileInfo->onof === '1' ? strval($fileInfo->pwd) : '', $fileInfo->is_newd . '/', $key);
	}
	/**
	 * 解析直链（文件分享id）
	 *
	 * @param  string  $shareId  文件分享id
	 * @param  string  $pwd      分享密码
	 * @param  string  $host     域名
	 * @param  null    $key      redis key
	 *
	 * @return array
	 * @throws \RedisException
	 */
	public static function parseUrlByShareId ($shareId, $pwd = '', $host = self::HOST, $key = null) {
	    if(empty($host))$host=self::HOST;
		if (strtolower(substr($shareId, 0, 1)) !== 'i')
			return msg(2, '文件分享id有误');
		$ins = self::instance();
		if (empty($key)) $key = implode(':', array_filter(['s', $shareId, $pwd]));
		if (null !== $url = $ins->cache_get($key)) {
			header('Location: ' . $url);
			exit();
		}
		$redirect_url = function ($url, $data) use ($ins, $key) {
			$obj = $ins->curl()->post($url, $data)->obj();
			if (@$obj->zt !== 1) return isset($obj->inf) ? $obj->inf : '解析直链失败1';
			$curl = $ins->curl()
				//->nobody()
				->redirect(false)
				->en_char('')
				->get($obj->dom . '/file/' . $obj->url);
			$url  = $curl->redirect_url();
			$html = $curl->html();
			if (empty($url)) {
				$ajax               = self::html_ajax($html);
				$ajax['data']['el'] = 2;
				sleep(2); // 这里必须加上延迟2秒
				$obj = $ins->curl()->post(self::url_fix($obj->dom . '/file/', $ajax['url']), $ajax['data'])->obj();
				$url = @$obj->url;
				if (@$obj->zt !== 1 || !filter_var($url, FILTER_VALIDATE_URL))
					return isset($obj->inf) ? $obj->inf : '解析直链失败2';
			}
			if (filter_var($url, FILTER_VALIDATE_URL)) {
				if ($key !== null) {
					parse_str(parse_url($url, PHP_URL_QUERY), $args);
					$expire = intval($args['e']) - time();
					$ins->cache_set($key, $url, $expire > 0 ? intval($expire / 100 * mt_rand(50, 95)) : 60 * 20);
				}
				header('Location: ' . $url);
				exit();
			}
			return '解析直链失败3';
		};
		$ret  = '解析直链失败';
		$html = $ins->curl()->get($host . $shareId)->html();
		if (preg_match('/<iframe\s+class="(ifr2|n_downlink)".*?src="(\/fn\?\w{3,}?)".*?><\/iframe>/i', $html, $m)) {
			// 不需要访问密码
			$html = $ins->curl()->get(self::url_fix($host, $m[2]))->html();
			if (false !== $ajax = self::html_ajax($html)) {
				$ret = $redirect_url(self::url_fix($host, $ajax['url']), $ajax['data']);
			}
		} else if (false !== $ajax = self::html_ajax($html)) {
			// 需要访问密码
			if ($pwd === '') return msg(4, '需要访问密码');
			$ajax['data']['p'] = $pwd;
			$ret               = $redirect_url(self::url_fix($host, $ajax['url']), $ajax['data']);
		}
		return msg(3, preg_match('/(<div\s+class="off\d?">){3}<\/div><\/div>(.+?)<\/div>/i', $html, $m) ? $m[2] : $ret);
	}
	/**
	 * 上传文件到指定文件夹
	 *
	 * @param  string  $folder_id  目标文件夹
	 * @param  array   $files
	 *
	 * @return array
	 */
	public static function upload ($folder_id, $files) {
		if (empty($folder_id)) $folder_id = '-1';
		$ins = self::instance();
		if (true !== $ret = $ins->isAdmin())
			return $ret;
		if (true !== $ret = $ins->getCookie())
			return $ret;
		if (empty($files) || !isset($files['file']))
			return msg(-1, '没有文件被上传');
		$file = $files['file'];
		$name = $file['name'];
		if (preg_match('/^(.*?)\.([^.]*)$/', $name, $m) && in_array(strtolower($m[2]), self::allowedExts)) {
			$ext = $m[2];
		} else {
			$ext  = 'it';
			$name .= '.' . $ext;
		}
		if (!in_array(strtolower($ext), self::allowedExts))
			return msg(1, '不支持的文件格式！');
		if ($file['size'] > 100 * 1024 * 1024)
			return msg(2, '文件大小不能超过100M！');
		if ($file['error'] > 0)
			return msg(3, '文件错误！');
		$temp = __DIR__ . DIRECTORY_SEPARATOR . '.temp' . DIRECTORY_SEPARATOR;
		$dir  = $temp . md5_file($file['tmp_name']) . DIRECTORY_SEPARATOR;
		if (!file_exists($dir))
			mkdir($dir, 0777, true);
		$path = $dir . $name;
		if (!move_uploaded_file($file['tmp_name'], $path))
			return msg(4, '上传失败！');
		$obj = $ins->curl()
			->timeout($ins->conf['upload_timeout'])
			->cookie($ins->conf['cookie'])
			->upload(self::API_UPLOAD, [
				'task'        => 1,
				'folder_id'   => $folder_id,
				'upload_file' => new CURLFile($path)
			])->obj();
		del_dir($dir);
		@rmdir($temp);
		if ($obj->zt !== 1)
			return msg(5, is_string($obj->info) ? $obj->info : '未知错误');
		return msg(0, ['name' => $name, 'id' => $obj->text[0]->id, 'pId' => $folder_id]);
	}
	/**
	 * 获取文件(夹)信息
	 *
	 * @param  string    $id     文件(夹)id
	 * @param  bool|int  $isdir  是否文件夹
	 *
	 * @return array
	 */
	public static function info ($id, $isdir = true) {
		$ins = self::instance();
		if (true !== $ret = $ins->isAdmin())
			return $ret;
		if (true !== $ret = $ins->getCookie())
			return $ret;
		if ($isdir) {
			if (false === $data = $ins->folderInfo($id))
				return msg(1, '获取文件夹数据失败');
		} else {
			if (false === $data = $ins->fileInfo($id))
				return msg(1, '获取文件数据失败');
		}
		return msg(0, $data);
	}
	/**
	 * 重命名文件夹
	 *
	 * @param  string  $id    文件夹id
	 * @param  string  $name  新文件夹名称
	 * @param  string  $desc  文件夹描述
	 *
	 * @return array
	 */
	public static function rename ($id, $name, $desc = '') {
		$ins = self::instance();
		if (true !== $ret = $ins->isAdmin())
			return $ret;
		if (true !== $ret = $ins->getCookie())
			return $ret;
		$obj = $ins->cCurl(4, [
			'folder_id'          => $id,
			'folder_name'        => $name,
			'folder_description' => $desc
		])->obj();
		if ($obj->zt !== 1)
			return msg(1, is_string($obj->info) ? $obj->info : '修改失败');
		return msg(0, is_string($obj->info) ? $obj->info : '修改成功');
	}
	/**
	 * 修改文件描述
	 *
	 * @param  string  $id    文件id
	 * @param  string  $desc  文件描述
	 *
	 * @return array
	 */
	public static function desc ($id, $desc = '') {
		$ins = self::instance();
		if (true !== $ret = $ins->isAdmin())
			return $ret;
		if (true !== $ret = $ins->getCookie())
			return $ret;
		$obj = $ins->cCurl(11, [
			'file_id' => $id,
			'desc'    => $desc
		])->obj();
		if ($obj->zt !== 1)
			return msg(1, is_string($obj->info) ? $obj->info : '修改失败');
		return msg(0, is_string($obj->info) ? $obj->info : '修改成功');
	}
	/**
	 * 新建文件夹
	 *
	 * @param  string  $folder_id  目标文件夹id
	 * @param  string  $name       文件夹名称
	 * @param  string  $pwd        文件夹密码
	 * @param  string  $desc       文件夹描述
	 *
	 * @return array
	 */
	public static function createFolder ($folder_id, $name, $pwd = '', $desc = '') {
		if (empty($folder_id)) $folder_id = -1;
		if ($pwd === null) $pwd = '';
		if ($desc === null) $desc = '';
		$ins = self::instance();
		if (true !== $ret = $ins->isAdmin())
			return $ret;
		if (true !== $ret = $ins->getCookie())
			return $ret;
		$obj = $ins->cCurl(2, [
			'parent_id'          => $folder_id,
			'folder_name'        => $name,
			'folder_description' => $desc
		])->obj();
		if ($obj->zt !== 1)
			return msg(1, is_string($obj->info) ? $obj->info : '创建失败');
		$obj2 = $ins->cCurl(16, [
			'folder_id' => $obj->text,
			'shows'     => 1,
			'shownames' => $pwd === '' ? $ins->conf['default_pwd'] : $pwd
		])->obj();
		if ($obj2->zt !== 1)
			return msg(0, is_string($obj2->info) ? $obj2->info : '创建成功但修改密码失败', ['url' => true]);
		return msg(0, is_string($obj->info) ? $obj->info : '创建成功', ['id' => $obj->text, 'url' => true]);
	}
	/**
	 * 移动文件
	 *
	 * @param  string  $folder_id  目标文件夹id
	 * @param  array   $file_id    待移动的文件id
	 *
	 * @return array
	 * @throws \Exception
	 */
	public static function moveFile ($folder_id, $file_id) {
		if (empty($folder_id)) $folder_id = -1;
		$ins = self::instance();
		if (true !== $ret = $ins->isAdmin())
			return $ret;
		if (true !== $ret = $ins->getCookie())
			return $ret;
		/**
		 * @var \Classes\Curl[] $curls
		 */
		$curls = [];
		$error = 0;
		$total = 0;
		foreach ($file_id as $id) {
			$curls[] = $ins->cCurl(20, ['folder_id' => $folder_id, 'file_id' => $id]);
			$total++;
		}
		Curl::multiple(function ($curl, $index, $ch) use (&$error) {
			$obj = $curl->obj();
			if ($obj->zt !== 1) $error++;
		}, ...$curls);
		if ($error > 0)
			return msg(1, $error . '个文件移动失败', $total !== $error ? ['url' => true] : null);
		return msg(0, '移动成功', ['url' => true]);
	}
	/**
	 * 删除文件（夹）
	 *
	 * @param  array  $files  ['file_id' => [], 'folder_id' => []]
	 *
	 * @return array
	 * @throws \Exception
	 */
	public static function delete ($files = []) {
		$ins = self::instance();
		if (true !== $ret = $ins->isAdmin())
			return $ret;
		if (true !== $ret = $ins->getCookie())
			return $ret;
		/**
		 * @var \Classes\Curl[] $curls
		 */
		$curls = [];
		$error = 0;
		$total = 0;
		foreach ($files as $key => $value) {
			if (!in_array($key, ['file_id', 'folder_id']) || $value === null || $value === '') continue;
			if (!is_array($value)) $value = [$value];
			foreach ($value as $v) {
				$curls[] = $ins->cCurl($key === 'file_id' ? 6 : 3, [$key => $v]);
				$total++;
			}
		}
		Curl::multiple(function ($curl, $index, $ch) use (&$error) {
			$obj = $curl->obj();
			if ($obj->zt !== 1) $error++;
		}, ...$curls);
		if ($error > 0)
			return msg(1, $error . '个文件(夹)删除失败', $total !== $error ? ['url' => true] : null);
		return msg(0, '删除成功', ['url' => true]);
	}
	/**
	 * 修改密码（2-12位数）
	 *
	 * @param  string    $id     文件(夹)id
	 * @param  string    $pwd    新密码
	 * @param  bool|int  $isdir  是否文件夹
	 *
	 * @return array
	 */
	public static function setPwd ($id, $pwd = '', $isdir = 1) {
		$ins = self::instance();
		if ($id === '')
			return msg(1, '根文件夹不允许设置密码');
		if (true !== $ret = $ins->isAdmin())
			return $ret;
		if (true !== $ret = $ins->getCookie())
			return $ret;
		if ($isdir) {
			if ($pwd === '') $pwd = $ins->conf['default_pwd'];
			$obj = $ins->cCurl(16, [
				'folder_id' => $id,
				'shows'     => $pwd === '' ? 0 : 1,
				'shownames' => $pwd
			])->obj();
		} else {
			$obj = $ins->cCurl(23, [
				'file_id'   => $id,
				'shows'     => $pwd === '' ? 0 : 1,
				'shownames' => $pwd
			])->obj();
		}
		if ($obj->zt !== 1)
			return msg(2, is_string($obj->info) ? $obj->info : '修改失败');
		return msg(0, '修改成功');
	}
	/**
	 * 管理员登录
	 *
	 * @param  string  $pass    管理员密码
	 * @param  int     $expiry  登录过期时间
	 *
	 * @return array
	 */
	public static function login ($pass,$cookie='', $expiry = 86400) {
		$ins = self::instance();
		if ($ins->conf['admin_pass'] !== $pass)return msg(1, '管理员密码错误');
		cookie('admin', Authcode::encode($pass, $_SERVER['REMOTE_ADDR'], $expiry));
        if(!empty($cookie)){
            $arr1=explode(';',$cookie);
            $list =[];foreach($arr1 as $v){if(empty($v))continue;$arr2=explode('=',trim($v));$list[$arr2[0]]=$arr2[1];}
            $ins->conf['cookie']=$list;
            $ins->arr2file($list['ylogin'],$list);
            cookie('admincookie', json_encode($list), $expiry);
        }
		return msg(0, '登陆成功', ['url' => true]);
	}
	/**
	 * 管理员退出登录
	 *
	 * @return array
	 */
	public static function logout () {
		$ins = self::instance();
		if (true !== $ret = $ins->isAdmin())
			return $ret;
		cookie('admin', '');
		return msg(0, '退出成功');
	}
	private function getCookie ($key = 'cookie') {
	    if($this->conf['cookie']['phpdisk_info']=='此处填写您的phpdisk_info' || empty($this->conf['cookie']['phpdisk_info'])){
           $admincookie=json_decode(cookie('admincookie'),true);
           if(!empty($admincookie) && is_array($admincookie))$this->conf['cookie']=$admincookie;
           else if($this->conf_ylogin){
             $arr =$this->arr2file($this->conf_ylogin);
             if(!empty($arr)){$this->conf['cookie']=$arr;}
           }
        }
		if (!empty($this->conf['cookie']) && isset($this->conf['cookie']['phpdisk_info']))
			return true;
		if (null !== $ret = $this->cache_get($key)) {
			$this->conf['cookie'] = $ret;
			return true;
		}
		/* 为防和谐，此处移除自动登录获取cookie相关代码 */
		return msg(11, '未配置蓝奏云网盘账号密码或cookie');
	}
	// 检测是否管理员
	private function isAdmin () {
		if (null === $str = cookie('admin'))
			return msg(21, '未登录', ['url' => true]);
		if (!($pass = Authcode::decode($str, $_SERVER['REMOTE_ADDR'])) || $pass !== $this->conf['admin_pass'])
			return msg(22, '登录已过期，请重新登录', ['url' => true]);
		return true;
	}
	/**
	 * 获取文件夹信息
	 *
	 * @param $folder_id
	 *
	 * @return object|false
	 */
	private function folderInfo ($folder_id) {
		$obj = $this->cCurl(18, ['folder_id' => $folder_id])->obj();
		if ($obj->zt !== 1)
			return false;
		if (isset($obj->info->des)) $obj->info->des = html_entity_decode($obj->info->des);
		return $obj->info;
	}
	/**
	 * 获取文件信息
	 *
	 * @param $file_id
	 *
	 * @return object|false
	 */
	private function fileInfo ($file_id) {
		$obj  = $this->cCurl(22, ['file_id' => $file_id])->obj(); // 密码
		$obj2 = $this->cCurl(12, ['file_id' => $file_id])->obj(); // 描述
		if ($obj->zt !== 1 || $obj2->zt !== 1)
			return false;
		$info       = $obj->info;
		$info->name = html_entity_decode($obj2->text);
		$info->des  = html_entity_decode($obj2->info);
		return $info;
	}
	private function curl ($ua = 'pc') {
		return curl()
			->ua($ua)
			->referer(self::HOST)
			->addHeader([
				'accept'          => 'text/html,application/xhtml+xml,application/xml',
				'accept-language' => 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
				//'X-Real-IP' => $_SERVER['REMOTE_ADDR'],
				'X-Forwarded-For' => $_SERVER['REMOTE_ADDR']
			]);
	}
    //文件缓存
    private function arr2file($filename, $arr = ''){
        $file = './data/'.$filename.'.php';
        if(empty($arr)){//读取
            if(file_exists($file)){
                $content = file_get_contents($file);
                return json_decode(substr($content,15),true);
            }else{
                return '';
            }
        }else{//写入
            $con = "<?php return;//".json_encode($arr);
            file_put_contents($file, $con);
            return true;
        }
    }
	private function cCurl ($task, $data = [], $ua = 'android') {
		$data['task'] = $task;
		return $this->curl($ua)
			->addCookie($this->conf['cookie'])
			->post(self::API, $data);
	}
	/**
	 * 提取html源码中的script代码并过滤掉干扰函数
	 *
	 * @param  string  $html  html源码
	 * @param  string  $fun   干扰函数名正则
	 *
	 * @return string
	 */
	private static function html_script ($html, $fun = 'woio\d*') {
		$script = '';
		if (preg_match_all('#<script.*?>([\s\S]*?)</script>#i', $html, $m) > 0) {
			$script = implode("\n", $m[1]);
			$script = preg_replace("#(^|\n)\s*function\s*{$fun}\s*(.*?)\s*\{[\s\S]*?\}\s*(\n|$)#i", '', $script);
		}
		return $script;
	}
	/**
	 * 提取ajax中的data并解析其中的变量
	 *
	 * @param  string  $data    data字符串
	 * @param  string  $script  script代码，用于提取解析data中的变量
	 *
	 * @return array|string[]
	 */
	private static function ajax_data ($data, $script) {
		if (!preg_match_all('/[\'"](\w+)[\'"]\s*:\s*(\w+|[\'"](.*?)[\'"])/', $data, $m))
			return [];
		$data = array_combine($m[1], $m[2]);
		$vars = preg_match_all('/\n\s*(var\s*)?([a-zA-Z_]\w*)\s*=\s*([\'"](.*)[\'"]|\d+)\s*;/', $script, $m) > 0
			? array_combine($m[2], $m[3]) : [];
		return array_map(function ($v) use ($vars) {
			return trim(preg_match('/^([a-zA-Z_]\w*)$/', $v) ? isset($vars[$v]) ? $vars[$v] : '' : $v, '"\' ');
		}, $data);
	}
	/**
	 * 提取html源码中的ajax并解析data中的变量
	 *
	 * @param  string  $html  html源码
	 *
	 * @return array|false
	 */
	private static function html_ajax ($html) {
		$script = self::html_script($html);
		if (preg_match('/[,{\n]\s*url\s*:\s*[\'"](.+?)[\'"]\s*,(?:[\s\S]*?\n+)?\s*data\s*:\s*{([\s\S]*?)}\s*,/i', $script, $m)) {
			return ['url' => $m[1], 'data' => self::ajax_data($m[2], $script)];
		}
		return false;
	}
	private static function url_fix ($host, $url) {
		return preg_match('#^(https?:)?//#i', $url) ? $url
			: rtrim($host, '/') . '/' . ltrim($url, '/');
	}
	/**
	 * 设置缓存
	 *
	 * @param  string  $key     缓存key
	 * @param  mixed   $value   缓存数据
	 * @param  int     $expire  缓存过期时间
	 *
	 * @return bool
	 * @throws \RedisException
	 */
	private function cache_set ($key, $value, $expire) {
		if ($this->redis === null) return Cache::set($key, $value, $expire);
		return $this->redis->set($key, is_array($value) ? arr2json($value) : $value, $expire);
	}
	/**
	 * 读取缓存
	 *
	 * @param  string  $key  缓存key
	 *
	 * @return mixed|null
	 * @throws \RedisException
	 */
	private function cache_get ($key) {
		if ($this->redis === null) return Cache::get($key);
		if (!$this->redis->exists($key)) return null;
		$ret = $this->redis->get($key);
		return (false === $obj = is_json($ret, true)) ? $ret : $obj;
	}
	/**
	 * 删除旧的缓存目录及文件, 仅保留当天的缓存
	 *
	 * @return void
	 */
	private function cache_clear () {
		$basename = basename(CACHE_PATH);
		array_map(function ($path) use ($basename) {
			$name = basename($path);
			if ('.' === $name || '..' === $name) return;
			if (is_dir($path)) {
				if ($name !== $basename) del_dir($path);
			} else if (!@unlink($path) && chmod($path, 0777))
				@unlink($path);
		}, glob(dirname(CACHE_PATH) . DIRECTORY_SEPARATOR . '{.*,*}', GLOB_BRACE));
	}
}